home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / packages / saveconf.el.z / saveconf.el
Encoding:
Text File  |  1998-05-21  |  10.5 KB  |  285 lines

  1. ;;; Save Emacs buffer and window configuration between editing sessions.
  2. ;;; Copyright (C) 1987, 1988, 1989 Kyle E. Jones
  3. ;;;
  4. ;;; This program is free software; you can redistribute it and/or modify
  5. ;;; it under the terms of the GNU General Public License as published by
  6. ;;; the Free Software Foundation; either version 1, or (at your option)
  7. ;;; any later version.
  8. ;;;
  9. ;;; This program is distributed in the hope that it will be useful,
  10. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;;; GNU General Public License for more details.
  13. ;;;
  14. ;;; A copy of the GNU General Public License can be obtained from the
  15. ;;; program's author (send electronic mail to kyle@cs.odu.edu) or from
  16. ;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
  17. ;;; 02139, USA.
  18. ;;;
  19. ;;; Send bug reports to kyle@cs.odu.edu.
  20.  
  21. ;;; Synched up with: Not in FSF.
  22.  
  23. ;; This package of functions gives Emacs the ability to remember which
  24. ;; files were being visited, the windows that were on them, and the
  25. ;; value of point in their buffers the last Emacs session in the same
  26. ;; directory.  This is an emulation of an old Gosling Emacs feature.
  27. ;;
  28. ;; The relevant commands are save-context and recover-context.
  29. ;;
  30. ;; Most of the time you'll want an Emacs session's context saved even if
  31. ;; you choose not to recover it later.  To avoid having to manually
  32. ;; M-x save-context at each emacs exit, put the line:
  33. ;;    (setq auto-save-and-recover-context t)
  34. ;; in your .emacs or in default.el in the lisp directory of the Emacs
  35. ;; distribution.  The context will then automatically be saved when
  36. ;; Emacs exits.
  37. ;;
  38. ;; By default only the contexts of visible buffers (buffers with windows
  39. ;; on them) are saved.  Setting the variable save-buffer-context to t
  40. ;; causes the contexts of all buffers to be saved.
  41. ;;
  42. ;; Put this file in the "lisp" directory of the emacs distribution in a
  43. ;; file called saveconf.el.  Byte-compile it.
  44. ;;
  45. ;; There are two ways to use this package.
  46. ;;   1) Put the line
  47. ;;       (require 'saveconf)
  48. ;;      in the file site-init.el in the lisp directory of the Emacs
  49. ;;      directory and rebuild Emacs.  If you get the "Pure Lisp storage
  50. ;;      exhausted" error message when rebuilding Emacs, increase PURESIZE
  51. ;;      in src/config.h by about 30000 bytes and try again.  It's almost
  52. ;;      certain that this will happen to you so you might as well increase
  53. ;;      PURESIZE beforehand.
  54. ;;
  55. ;;      This is the preferred mode of operation because it allows the
  56. ;;      package to become part of Emacs' startup sequence and automatically
  57. ;;      restore context in a directory if Emacs is invoked without any
  58. ;;      command line arguments.
  59. ;;
  60. ;;   2) Put these lines
  61. ;;       (require 'saveconf)
  62. ;;       (if (null (cdr command-line-args))
  63. ;;           (setq inihibit-startup-message (recover-context)))
  64. ;;      at the end of your .emacs file or the default.el file in the
  65. ;;      lisp directory of the Emacs distribution.  This causes the
  66. ;;      context saved in the current directory to be recovered whenever
  67. ;;      Emacs is invoked without any arguments.
  68.  
  69. (provide 'saveconf)
  70.  
  71. (defconst save-context-version "Norma Jean"
  72.   "A unique string which is placed at the beginning of every saved context
  73. file.  If the string at the beginning of the context file doesn't match the
  74. value of this variable the `recover-context' command will ignore the file's
  75. contents.")
  76.  
  77. (defvar auto-save-and-recover-context nil
  78.   "*If non-nil the `save-context' command will always be run before Emacs is
  79. exited.  Also upon Emacs startup, if this variable is non-nil and Emacs is
  80. passed no command line arguments, `recover-context' will be run.")
  81.  
  82. (defvar save-buffer-context nil
  83.   "*If non-nil the `save-context' command will save the context
  84. of buffers that are visiting files, as well as the contexts of buffers
  85. that have windows.")
  86.  
  87. (defvar save-context-predicate
  88.   (function (lambda (w)
  89.           (and (buffer-file-name (window-buffer w))
  90.            (not (string-match "^\\(/usr\\)?/tmp/"
  91.                       (buffer-file-name (window-buffer w)))))))
  92.   "*Value is a predicate function which determines which windows' contexts
  93. are saved.  When the `save-context' command is invoked, this function will
  94. be called once for each existing Emacs window.  The function should accept
  95. one argument which will be a window object, and should return non-nil if
  96. the window's context should be saved.")
  97.  
  98.  
  99. ;; kill-emacs' function definition must be saved
  100. (if (not (fboundp 'just-kill-emacs))
  101.     (fset 'just-kill-emacs (symbol-function 'kill-emacs)))
  102.  
  103. ;; Make Emacs call recover-context at startup if appropriate.
  104. (setq top-level
  105.       (list 'let '((starting-up (not command-line-processed)))
  106.         (list 'prog1
  107.           top-level
  108.           '(and starting-up auto-save-and-recover-context
  109.             (null (cdr command-line-args)) (recover-context)))))
  110.  
  111. (defun kill-emacs (&optional query)
  112.   "End this Emacs session.
  113. Prefix ARG or optional first ARG non-nil means exit with no questions asked,
  114. even if there are unsaved buffers.  If Emacs is running non-interactively
  115. and ARG is an integer, then Emacs exits with ARG as its exit code.
  116.  
  117. If the variable `auto-save-and-restore-context' is non-nil,
  118. the function save-context will be called first."
  119.   (interactive "P")
  120.   ;; check the purify flag.  try to save only if this is a dumped Emacs.
  121.   ;; saving context from a undumped Emacs caused a NULL pointer to be
  122.   ;; referenced through.  I'm not sure why.
  123.   (if (and auto-save-and-recover-context (null purify-flag))
  124.       (save-context))
  125.   (just-kill-emacs query))
  126.  
  127. (defun save-context ()
  128.   "Save context of all Emacs windows (files visited and position of point).
  129. The information goes into a file called .emacs_<username> in the directory
  130. where the Emacs session was started.  The context can be recovered with the
  131. `recover-context' command, provided you are in the same directory where
  132. the context was saved.
  133.  
  134. If the variable `save-buffer-context' is non-nil, the context of all buffers
  135. visiting files will be saved as well.
  136.  
  137. Window sizes and shapes are not saved, since these may not be recoverable
  138. on terminals with a different number of rows and columns."
  139.   (interactive)
  140.   (condition-case error-data
  141.       (let (context-buffer mark save-file-name)
  142.     (setq save-file-name (concat (original-working-directory)
  143.                      ".emacs_" (user-login-name)))
  144.     (if (not (file-writable-p save-file-name))
  145.         (if (file-writable-p (original-working-directory))
  146.         (error "context is write-protected, %s" save-file-name)
  147.           (error "can't access directory, %s"
  148.              (original-working-directory))))
  149.     ;;
  150.     ;; set up a buffer for the saved context information
  151.     ;; Note that we can't set the visited file yet, because by
  152.     ;; giving the buffer a file to visit we are making it
  153.     ;; eligible to have it's context saved.
  154.     ;;
  155.     (setq context-buffer (get-buffer-create " *Context Info*"))
  156.     (set-buffer context-buffer)
  157.     (erase-buffer)
  158.     (set-buffer-modified-p nil)
  159.     ;;
  160.     ;; record the context information
  161.     ;;
  162.     (mapcar
  163.      (function
  164.       (lambda (w)
  165.         (cond ((funcall save-context-predicate w)
  166.            (prin1 (buffer-file-name (window-buffer w)) context-buffer)
  167.            (princ " " context-buffer)
  168.            (prin1 (window-point w) context-buffer)
  169.            (princ "\n" context-buffer)))))
  170.      (window-list))
  171.     
  172.     ;;
  173.     ;; nil is the data sentinel.  We will insert it later if we
  174.     ;; need it but for now just remember where the last line of
  175.     ;; window context ended.
  176.     ;;
  177.     (setq mark (point))
  178.  
  179.     ;;
  180.     ;; If `save-buffer-context' is non-nil we save buffer contexts.
  181.     ;;
  182.     (if save-buffer-context
  183.         (mapcar
  184.          (function
  185.           (lambda (b)
  186.         (set-buffer b)
  187.         (cond (buffer-file-name
  188.                (prin1 buffer-file-name context-buffer)
  189.                (princ " " context-buffer)
  190.                (prin1 (point) context-buffer)
  191.                (princ "\n" context-buffer)))))
  192.          (buffer-list)))
  193.  
  194.     ;;
  195.     ;; If the context-buffer contains information, we add the version
  196.     ;;   string and sentinels, and write out the saved context.
  197.     ;; If the context-buffer is empty, we don't create a file at all.
  198.     ;; If there's an old saved context in this directory we attempt
  199.     ;;   to delete it.
  200.     ;;
  201.     (cond ((buffer-modified-p context-buffer)
  202.            (set-buffer context-buffer)
  203.            (setq buffer-offer-save nil)
  204.            ;; sentinel for EOF
  205.            (insert "nil\n")
  206.            ;; sentinel for end of window contexts
  207.            (goto-char mark)
  208.            (insert "nil\n")
  209.            ;; version string
  210.            (goto-char (point-min))
  211.            (prin1 save-context-version context-buffer)
  212.            (insert "\n\n")
  213.            ;; so kill-buffer won't need confirmation later
  214.            (set-buffer-modified-p nil)
  215.            ;; save it
  216.            (write-region (point-min) (point-max) save-file-name
  217.                  nil 'quiet))
  218.           (t (condition-case data
  219.              (delete-file save-file-name) (error nil))))
  220.  
  221.     (kill-buffer context-buffer))
  222.     (error nil)))
  223.  
  224. (defun recover-context ()
  225.   "Recover an Emacs context saved by `save-context' command.
  226. Files that were visible in windows when the context was saved are visited and
  227. point is set in each window to what is was when the context was saved."
  228.   (interactive)
  229.   (condition-case error-data
  230.       ;;
  231.       ;; Set up some local variables.
  232.       ;;
  233.       (let (sexpr context-buffer recover-file-name)
  234.     (setq recover-file-name (concat (original-working-directory)
  235.                     ".emacs_" (user-login-name)))
  236.     (if (not (file-readable-p recover-file-name))
  237.         (error "can't access context, %s" recover-file-name))
  238.     ;;
  239.     ;; create a temp buffer and copy the saved context into it.
  240.     ;;
  241.     (setq context-buffer (get-buffer-create " *Recovered Context*"))
  242.     (set-buffer context-buffer)
  243.     (erase-buffer)
  244.     (insert-file-contents recover-file-name nil)
  245.     ;; so kill-buffer won't need confirmation later
  246.     (set-buffer-modified-p nil)
  247.     ;;
  248.     ;; If it's empty forget it.
  249.     ;;
  250.     (if (zerop (buffer-size))
  251.         (error "context file is empty, %s" recover-file-name))
  252.     ;;
  253.     ;; check the version and make sure it matches ours
  254.     ;;
  255.     (setq sexpr (read context-buffer))
  256.     (if (not (equal sexpr save-context-version))
  257.         (error "version string incorrect, %s" sexpr))
  258.     ;;
  259.     ;; Recover the window contexts
  260.     ;;
  261.     (while (setq sexpr (read context-buffer))
  262.       (select-window (get-largest-window))
  263.       (if (buffer-file-name)
  264.           (split-window))
  265.       (other-window 1)
  266.       (find-file sexpr)
  267.       (goto-char (read context-buffer)))
  268.     ;;
  269.     ;; Recover buffer contexts, if any.
  270.     ;;
  271.     (while (setq sexpr (read context-buffer))
  272.       (set-buffer (find-file-noselect sexpr t))
  273.       (if (zerop (buffer-size))
  274.           (kill-buffer (current-buffer))
  275.         (goto-char (read context-buffer))))
  276.     (bury-buffer "*scratch*")
  277.     (kill-buffer context-buffer)
  278.     t )
  279.     (error nil)))
  280.      
  281. (defun original-working-directory ()
  282.   (save-excursion
  283.     (set-buffer (get-buffer-create "*scratch*"))
  284.     default-directory))
  285.